import 'package:base/common/widgets/text_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';

class TextLayoutWithAnimation extends StatelessWidget {
  final TextController controller;
  final Color defaultUnderlineColor;

  const TextLayoutWithAnimation({
    Key? key,
    required this.controller,
    this.defaultUnderlineColor = Colors.black,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: controller,
      builder: (context, child) {
        // Calculate the total size needed for the text
        Size requiredSize = Size.zero;
        for (var chip in controller.chipLayoutInfo) {
          double right = chip.offset.dx + chip.size.width;
          double bottom = chip.offset.dy + chip.size.height;
          requiredSize = Size(
            requiredSize.width > right ? requiredSize.width : right,
            requiredSize.height > bottom ? requiredSize.height : bottom,
          );
        }

        return CustomPaint(
          size: requiredSize,
          painter: CustomTextPainter(
            controller: controller,
            defaultUnderlineColor: defaultUnderlineColor,
          ),
        );
      },
    );
  }
}

class CustomTextPainter extends CustomPainter {
  final TextController controller;
  final Color defaultUnderlineColor;
  final Map<String, TextPainter> _textPainterCache = {};

  CustomTextPainter({
    required this.controller,
    required this.defaultUnderlineColor,
  });

  @override
  void paint(Canvas canvas, Size size) {
    // First draw all text
    for (var chip in controller.chipLayoutInfo) {
      _drawText(canvas, chip);
    }

    // Then draw all underlines to ensure they appear below the text
    _drawUnderlines(canvas, controller.lineInfo);
  }

  void _drawText(Canvas canvas, ChipLayoutInfo chip) {
    // Use cached TextPainter if available
    final textPainter = _getTextPainter(chip.text);
    textPainter.paint(canvas, chip.offset);
  }

  TextPainter _getTextPainter(String text) {
    if (!_textPainterCache.containsKey(text)) {
      final painter = TextPainter(
        text: TextSpan(text: text, style: controller.style),
        textDirection: TextDirection.ltr,
      );
      painter.layout();
      _textPainterCache[text] = painter;
    }
    return _textPainterCache[text]!;
  }

  void _drawUnderlines(Canvas canvas, List<LineInfo> lineInfos) {
    for (var lineInfo in lineInfos) {
      final paint = Paint()
        ..color = lineInfo.color ?? defaultUnderlineColor
        ..strokeWidth = 2
        ..strokeCap = StrokeCap.round; // 使下划线端点圆润

      // Calculate the y position to be slightly below the text
      final adjustedStartY = lineInfo.startOffset.dy + controller.style.fontSize! * 1.1;
      final adjustedEndY = lineInfo.endOffset.dy + controller.style.fontSize! * 1.1;

      canvas.drawLine(
        Offset(lineInfo.startOffset.dx, adjustedStartY),
        Offset(lineInfo.endOffset.dx, adjustedEndY),
        paint,
      );
    }
  }

  @override
  bool shouldRepaint(CustomTextPainter oldDelegate) {
    return oldDelegate.controller != controller ||
        oldDelegate.defaultUnderlineColor != defaultUnderlineColor;
  }

  // Clean up resources
  void dispose() {
    _textPainterCache.clear();
  }
}